home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / cp2dekit / samples / devwgus.cpp < prev    next >
C/C++ Source or Header  |  1996-12-29  |  34KB  |  1,702 lines

  1. //***************************************************************************
  2. //
  3. // this file is (c) '94-'96 Niklas Beisert
  4. //
  5. // this file is part of the cubic player development kit.
  6. // you may only use/modify/spread this file under the terms stated
  7. // in the cubic player development kit accompanying documentation.
  8. //
  9. //***************************************************************************
  10.  
  11. //[sound]
  12. //  playerdevices=devpWSS devpGUS devpSB devpPAS devpNone devpDisk
  13. //[devwGUS]
  14. //  link=devwgus
  15. //  driver=_mcpUltraSound
  16. //  addprocs=_mcpGUSAdd
  17. //  handle=2
  18. //  gusSlowUpload=on
  19. //  gusSystemTimer=on
  20.  
  21.  
  22.  
  23. // wavetable device example
  24.  
  25. #include <time.h>
  26. #include <string.h>
  27. #include <conio.h>
  28. #include <stdlib.h>
  29. #include <ctype.h>
  30. #include "ss.h"
  31. #include "mcp.h"
  32. #include "mix.h"
  33. #include "irq.h"
  34. #include "dma.h"
  35. #include "timer.h"
  36.  
  37. #define MAXSAMPLES 256
  38.  
  39. #define SS_GUS_SLOWUPLOAD 1
  40. #define SS_GUS_SYSTIMER 2
  41.  
  42. extern "C" extern sounddevice mcpUltraSound;
  43.  
  44. static unsigned short gusPort;
  45. static unsigned char gusDMA;
  46. static unsigned char gusIRQ;
  47. static unsigned char gusDMA2;
  48. static unsigned char gusIRQ2;
  49. static unsigned long gusMem;
  50. static unsigned char activevoices;
  51.  
  52.  
  53. unsigned long muldiv64(unsigned long, unsigned long, unsigned long);
  54. //#pragma aux muldiv64 parm [eax] [edx] [ecx] = "mul edx" "div ecx"
  55. #pragma aux muldiv64 parm [eax] [edx] [ecx] modify [ebx] = "mul edx" "mov ebx,ecx" "shr ebx,1" "add eax,ebx" "adc edx,0" "div ecx"
  56.  
  57. static char getcfg()
  58. {
  59.   char *ptr=getenv("ULTRASND");
  60.   if (!ptr)
  61.     return 0;
  62.   while (isspace(*ptr))
  63.     ptr++;
  64.   if (!ptr)
  65.     return 0;
  66.   gusPort=strtoul(ptr, 0, 16);
  67.   while ((*ptr!=',')&&*ptr)
  68.     ptr++;
  69.   if (!*ptr++)
  70.     return 0;
  71.   gusDMA=strtoul(ptr, 0, 10)&7;
  72.   while ((*ptr!=',')&&*ptr)
  73.     ptr++;
  74.   if (!*ptr++)
  75.     return 0;
  76.   gusDMA2=strtoul(ptr, 0, 10)&7;
  77.   while ((*ptr!=',')&&*ptr)
  78.     ptr++;
  79.   if (!*ptr++)
  80.     return 0;
  81.   gusIRQ=strtoul(ptr, 0, 10)&15;
  82.   while ((*ptr!=',')&&*ptr)
  83.     ptr++;
  84.   if (!*ptr++)
  85.     return 0;
  86.   gusIRQ2=strtoul(ptr, 0, 10)&15;
  87.   return 1;
  88. }
  89.  
  90. static unsigned char inpGUS(unsigned short p)
  91. {
  92.   return inp(gusPort+p);
  93. }
  94.  
  95. static unsigned short inpwGUS(unsigned short p)
  96. {
  97.   return inpw(gusPort+p);
  98. }
  99.  
  100. static void delayGUS()
  101. {
  102.   inp(gusPort+0x107);
  103.   inp(gusPort+0x107);
  104.   inp(gusPort+0x107);
  105.   inp(gusPort+0x107);
  106.   inp(gusPort+0x107);
  107.   inp(gusPort+0x107);
  108.   inp(gusPort+0x107);
  109.   inp(gusPort+0x107);
  110. }
  111.  
  112. static void outpGUS(unsigned short p, unsigned char v)
  113. {
  114.   outp(gusPort+p,v);
  115. }
  116.  
  117. static void outpwGUS(unsigned short p, unsigned short v)
  118. {
  119.   outpw(gusPort+p,v);
  120. }
  121.  
  122. static void outGUS(unsigned char c, unsigned char v)
  123. {
  124.   outp(gusPort+0x103, c);
  125.   outp(gusPort+0x105, v);
  126. }
  127.  
  128. static void outdGUS(unsigned char c, unsigned char v)
  129. {
  130.   outp(gusPort+0x103, c);
  131.   outp(gusPort+0x105, v);
  132.   delayGUS();
  133.   outp(gusPort+0x105, v);
  134. }
  135.  
  136. static void outwGUS(unsigned char c, unsigned short v)
  137. {
  138.   outp(gusPort+0x103, c);
  139.   outpw(gusPort+0x104, v);
  140. }
  141.  
  142. static unsigned char inGUS(unsigned char c)
  143. {
  144.   outp(gusPort+0x103, c);
  145.   return inp(gusPort+0x105);
  146. }
  147.  
  148. static unsigned short inwGUS(unsigned char c)
  149. {
  150.   outp(gusPort+0x103, c);
  151.   return inpw(gusPort+0x104);
  152. }
  153.  
  154. static inline void outpGUS0(unsigned char v)
  155. {
  156.   outpGUS(0x00, v);
  157. }
  158.  
  159. static inline void outpGUS8(unsigned char v)
  160. {
  161.   outpGUS(0x08, v);
  162. }
  163.  
  164. static inline void outpGUS9(unsigned char v)
  165. {
  166.   outpGUS(0x09, v);
  167. }
  168.  
  169. static inline void outpGUSB(unsigned char v)
  170. {
  171.   outpGUS(0x0B, v);
  172. }
  173.  
  174. static inline void outpGUSF(unsigned char v)
  175. {
  176.   outpGUS(0x0F, v);
  177. }
  178.  
  179. static inline unsigned char peekGUS(unsigned long adr)
  180. {
  181.   outwGUS(0x43, adr);
  182.   outdGUS(0x44, adr>>16);
  183.   return inpGUS(0x107);
  184. }
  185.  
  186. static inline void pokeGUS(unsigned long adr, unsigned char data)
  187. {
  188.   outwGUS(0x43, adr);
  189.   outdGUS(0x44, adr>>16);
  190.   outpGUS(0x107, data);
  191. }
  192.  
  193. static inline void selvoc(char ch)
  194. {
  195.   outpGUS(0x102, ch);
  196. }
  197.  
  198. static inline void setfreq(unsigned short frq)
  199. {
  200.   outwGUS(0x01, frq&~1);
  201. }
  202.  
  203. static inline void setvol(unsigned short vol)
  204. {
  205.   outwGUS(0x09, vol<<4);
  206. }
  207.  
  208. static inline unsigned short getvol()
  209. {
  210.   return inwGUS(0x89)>>4;
  211. }
  212.  
  213. static inline void setpan(unsigned char pan)
  214. {
  215.   outGUS(0x0C, pan);
  216. }
  217.  
  218. static inline void setpoint8(unsigned long p, unsigned char t)
  219. {
  220.   t=(t==1)?0x02:(t==2)?0x04:0x0A;
  221.   outwGUS(t, (p>>7)&0x1FFF);
  222.   outwGUS(t+1, p<<9);
  223. }
  224.  
  225. static inline unsigned long getpoint8(unsigned char t)
  226. {
  227.   t=(t==1)?0x82:(t==2)?0x84:0x8A;
  228.   return (inwGUS(t)<<16)|inwGUS(t+1);
  229. }
  230.  
  231. static inline void setmode(unsigned char m)
  232. {
  233.   outdGUS(0x00, m);
  234. }
  235.  
  236. static inline unsigned char getmode()
  237. {
  238.   return inGUS(0x80);
  239. }
  240.  
  241. static inline void setvst(unsigned char s)
  242. {
  243.   outGUS(0x07, s);
  244. }
  245.  
  246. static inline void setvend(unsigned char s)
  247. {
  248.   outGUS(0x08, s);
  249. }
  250.  
  251. static inline void setvmode(unsigned char m)
  252. {
  253.   outdGUS(0x0D, m);
  254. }
  255.  
  256. static inline unsigned char getvmode()
  257. {
  258.   return inGUS(0x8D);
  259. }
  260.  
  261. static inline void settimer(unsigned char o)
  262. {
  263.   outGUS(0x45, o);
  264. }
  265.  
  266. static inline void settimerlen(unsigned char l)
  267. {
  268.   outGUS(0x46, l);
  269. }
  270.  
  271. static int testPort(unsigned short port)
  272. {
  273.   gusPort=port;
  274.  
  275.   outGUS(0x4C, 0);
  276.  
  277.   delayGUS();
  278.   delayGUS();
  279.  
  280.   outGUS(0x4C, 1);
  281.  
  282.   delayGUS();
  283.   delayGUS();
  284.  
  285.   char v0=peekGUS(0);
  286.   char v1=peekGUS(1);
  287.  
  288.   pokeGUS(0,0xAA);
  289.   pokeGUS(1,0x55);
  290.  
  291.   char gus=peekGUS(0)==0xAA;
  292.  
  293.   pokeGUS(0,v0);
  294.   pokeGUS(1,v1);
  295.  
  296.   if (!gus)
  297.     return 0;
  298.  
  299.   int i,j;
  300.   unsigned char oldmem[4];
  301.   for (i=0; i<4; i++)
  302.     oldmem[i]=peekGUS(i*256*1024);
  303.  
  304.   pokeGUS(0,1);
  305.   pokeGUS(0,1);
  306.   gusMem=256*1024;
  307.   for (i=1; i<4; i++)
  308.   {
  309.     pokeGUS(i*256*1024, 15+i);
  310.     pokeGUS(i*256*1024, 15+i);
  311.     for (j=0; j<i; j++)
  312.     {
  313.       if (peekGUS(j*256*1024)!=(1+j))
  314.         break;
  315.       if (peekGUS(j*256*1024)!=(1+j))
  316.         break;
  317.     }
  318.     if (j!=i)
  319.       break;
  320.     if (peekGUS(i*256*1024)!=(15+i))
  321.       break;
  322.     if (peekGUS(i*256*1024)!=(15+i))
  323.       break;
  324.     pokeGUS(i*256*1024, 1+i);
  325.     pokeGUS(i*256*1024, 1+i);
  326.     gusMem+=256*1024;
  327.   }
  328.  
  329.   for (i=3; i>=0; i--)
  330.   {
  331.     pokeGUS(i*256*1024, oldmem[i]);
  332.     pokeGUS(i*256*1024, oldmem[i]);
  333.   }
  334.  
  335.   return 1;
  336. }
  337.  
  338. static void initgus(char voices)
  339. {
  340.   if (voices<14)
  341.     voices=14;
  342.   if (voices>32)
  343.     voices=32;
  344.  
  345.   activevoices=voices;
  346.  
  347.   int i;
  348.  
  349.   outGUS(0x4C, 0);
  350.   for (i=0; i<10; i++)
  351.     delayGUS();
  352.  
  353.   outGUS(0x4C, 1);
  354.   for (i=0; i<10; i++)
  355.     delayGUS();
  356.  
  357.   outGUS(0x41, 0x00);
  358.   outGUS(0x45, 0x00);
  359.   outGUS(0x49, 0x00);
  360.  
  361.   outGUS(0xE, (voices-1)|0xC0);
  362.  
  363.   inpGUS(0x6);
  364.   inGUS(0x41);
  365.   inGUS(0x49);
  366.   inGUS(0x8F);
  367.  
  368.   for (i=0; i<32; i++)
  369.   {
  370.     selvoc(i);
  371.     setvol(0);  // vol=0
  372.     setmode(3);  // stop voice
  373.     setvmode(3);  // stop volume
  374.     setpoint8(0,0);
  375.     outGUS(0x06, 63);
  376.     delayGUS();
  377.   }
  378.  
  379.   inpGUS(0x6);
  380.   inGUS(0x41);
  381.   inGUS(0x49);
  382.   inGUS(0x8F);
  383.  
  384.   outGUS(0x4C,0x07);
  385. /*
  386.   unsigned char l1="\x00\x00\x01\x03\x00\x02\x00\x04\x00\x00\x00\x05\x06\x00\x00\x07"[gusIRQ]|((gusIRQ==gusIRQ2)?0x40:"\x00\x00\x08\x18\x00\x10\x00\x20\x00\x00\x00\x28\x30\x00\x00\x38"[gusIRQ2]);
  387.   unsigned char l2="\x00\x01\x00\x02\x00\x03\x04\x05"[gusDMA]|((gusDMA==gusDMA2)?0x40:"\x00\x08\x00\x10\x00\x18\x20\x28"[gusDMA2]);
  388.  
  389.   outpGUSF(5);
  390.   outpGUS0(0x0B);
  391.   outpGUSB(0);
  392.   outpGUSF(0);
  393.  
  394.   outpGUS0(0x0B);
  395.   outpGUSB(l2|0x80);
  396.   outpGUS0(0x4B);
  397.   outpGUSB(l1);
  398.   outpGUS0(0x0B);
  399.   outpGUSB(l2);
  400.   outpGUS0(0x4B);
  401.   outpGUSB(l1);
  402. */
  403.   selvoc(0);
  404.   outpGUS0(0x08);
  405.   selvoc(0);
  406. /*
  407.   outGUS(0x4C,0x01);
  408.   settimer(0x00);   // stop timer
  409.   outpGUS8(0x04);
  410.   outpGUS9(0x80);
  411. */
  412. }
  413.  
  414.  
  415.  
  416. struct guschan
  417. {
  418.   unsigned long startpos;
  419.   unsigned long endpos;
  420.   unsigned long loopstart;
  421.   unsigned long loopend;
  422.   unsigned long samprate;
  423.   unsigned char redlev;
  424.  
  425.   unsigned short cursamp;
  426.   unsigned char mode;
  427.  
  428.   unsigned short voll;
  429.   unsigned short volr;
  430.  
  431.   unsigned char inited;
  432.   signed char chstatus;
  433.   signed short nextsample;
  434.   signed long nextpos;
  435.   unsigned char orgloop;
  436.   signed char loopchange;
  437.  
  438.   unsigned long orgfreq;
  439.   unsigned long orgdiv;
  440.   unsigned short orgvol;
  441.   signed short orgpan;
  442.   unsigned char pause;
  443.   unsigned char wasplaying;
  444.  
  445.   void *smpptr;
  446. };
  447.  
  448. struct gussample
  449. {
  450.   signed long pos;
  451.   unsigned long length;
  452.   unsigned long loopstart;
  453.   unsigned long loopend;
  454.   unsigned long samprate;
  455.   int type;
  456.   unsigned char redlev;
  457.   void *ptr;
  458. };
  459.  
  460. static unsigned short linvol[513];
  461. static unsigned long mempos;
  462. static gussample samples[MAXSAMPLES];
  463. static unsigned short samplenum;
  464.  
  465. static unsigned char channelnum;
  466. static void (*playerproc)();
  467. static guschan channels[32];
  468. static unsigned long gtimerlen;
  469. static unsigned long gtimerpos;
  470. static unsigned long stimerlen;
  471. static unsigned long stimerpos;
  472. static char __far *stack;
  473. static const unsigned long stacksize=8192;
  474. static unsigned char stackused;
  475. static void __far *oldssesp;
  476. static unsigned short relspeed;
  477. static unsigned long orgspeed;
  478. static unsigned char mastervol;
  479. static signed char masterpan;
  480. static signed char masterbal;
  481. static unsigned short masterfreq;
  482. static unsigned long amplify;
  483.  
  484. static unsigned char paused;
  485. static unsigned char doublechan;
  486.  
  487. static __segment dmasel;
  488. static void *dmabuf;
  489. static int dmalen;
  490. static volatile unsigned char dmaactive;
  491. static void *dmaxfer;
  492. static unsigned long dmaleft;
  493. static unsigned long dmapos;
  494. static unsigned char dma16bit;
  495. static unsigned char doslowupload;
  496. static unsigned char usesystimer;
  497.  
  498. static unsigned char filter;
  499.  
  500.  
  501. static void fadevol(unsigned short v)
  502. {
  503.   unsigned short start=getvol();
  504.   unsigned short end=v;
  505.   unsigned char vmode;
  506.   if (abs((short)(start-end))<64)
  507.   {
  508.     setvol(end);
  509.     return;
  510.   }
  511.  
  512.   if (start>end)
  513.   {
  514.     unsigned short t=start;
  515.     start=end;
  516.     end=t;
  517.     vmode=0x40;
  518.   }
  519.   else
  520.     vmode=0;
  521.   if (start<64)
  522.     start=64;
  523.   if (end>4032)
  524.     end=4032;
  525.   setvst(start>>4);
  526.   setvend(end>>4);
  527.   setvmode(vmode);
  528. }
  529.  
  530. static inline void fadevoldown()
  531. {
  532.   setvst(0x04);
  533.   setvend(0xFC);
  534.   setvmode(0x40);
  535. }
  536.  
  537.  
  538. static void processtick()
  539. {
  540.   int i;
  541.  
  542.   for (i=0; i<channelnum; i++)
  543.   {
  544.     guschan &c=channels[i];
  545.     if (c.inited&&(c.chstatus||(c.nextpos!=-1)))
  546.     {
  547.       selvoc(i);
  548.       setmode(c.mode|3);
  549.       fadevoldown();
  550.     }
  551.  
  552.     c.chstatus=0;
  553.   }
  554.  
  555.   for (i=0; i<channelnum; i++)
  556.   {
  557.     selvoc(i);
  558.     while (!(getvmode()&1));
  559.   }
  560.  
  561.   for (i=0; i<channelnum; i++)
  562.   {
  563.     guschan &c=channels[i];
  564.     selvoc(i);
  565.     if (c.inited)
  566.     {
  567.       if (c.nextsample!=-1)
  568.       {
  569.         gussample &s=samples[c.nextsample];
  570.         unsigned char bit16=!!(s.type&mcpSamp16Bit);
  571.         c.startpos=s.pos;
  572.         if (bit16)
  573.           c.startpos=(c.startpos&0xC0000)|((c.startpos>>1)&0x1FFFF)|0x20000;
  574.         c.endpos=c.startpos+s.length;
  575.         c.loopstart=c.startpos+s.loopstart;
  576.         c.loopend=c.startpos+s.loopend;
  577.         c.samprate=s.samprate;
  578.         c.redlev=s.redlev;
  579.         c.smpptr=s.ptr;
  580.         c.mode=0;
  581.         if (bit16)
  582.           c.mode|=0x04;
  583.         c.cursamp=c.nextsample;
  584.         c.orgloop=0;
  585.         if (s.type&mcpSampLoop)
  586.         {
  587.           c.orgloop=1;
  588.           c.mode|=0x08;
  589.           if (s.type&mcpSampBiDi)
  590.             c.mode|=0x10;
  591.           setpoint8(c.loopstart, 1);
  592.           setpoint8(c.loopend, 2);
  593.         }
  594.         else
  595.         {
  596.           setpoint8(c.startpos, 1);
  597.           setpoint8(c.endpos, 2);
  598.         }
  599.       }
  600.       if (c.nextpos!=-1)
  601.       {
  602.         unsigned long pos=c.startpos+(c.nextpos>>c.redlev);
  603.         if (c.mode&0x08)
  604.         {
  605.           if (pos>=c.loopend)
  606.             pos=c.loopstart+(pos-c.loopstart)%(c.loopend-c.loopstart);
  607.         }
  608.         else
  609.           if (pos>=c.endpos)
  610.             pos=c.endpos-1;
  611.         setpoint8(pos, 0);
  612.         setmode(c.mode|(getmode()&0x40));
  613.       }
  614.       if (c.loopchange!=-1)
  615.       {
  616.         if (c.loopchange&&c.orgloop)
  617.           c.mode|=0x08;
  618.         else
  619.           c.mode&=~0x08;
  620.         setmode(c.mode|(getmode()&0x40));
  621.         if (c.mode&0x08)
  622.         {
  623.           setpoint8(c.loopstart, 1);
  624.           setpoint8(c.loopend, 2);
  625.         }
  626.         else
  627.         {
  628.           setpoint8(c.startpos, 1);
  629.           setpoint8(c.endpos, 2);
  630.         }
  631.       }
  632.       if (!(getmode()&1))
  633.       {
  634.         short v,p;
  635.         v=c.voll+c.volr;
  636.         if (v)
  637.           setpan((15*c.volr+v/2)/v);
  638.         fadevol(c.pause?0:linvol[v]);
  639.         setfreq(muldiv64(muldiv64(c.orgfreq, c.samprate*masterfreq, c.orgdiv), activevoices, 154350));
  640.       }
  641.       else
  642.         fadevoldown();
  643.     }
  644.     else
  645.       fadevoldown();
  646.  
  647.     c.nextsample=-1;
  648.     c.nextpos=-1;
  649.     c.loopchange=-1;
  650.   }
  651.  
  652.   playerproc();
  653.  
  654.   stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
  655.   gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
  656. }
  657.  
  658. static void processtickdc()
  659. {
  660.   int i;
  661.  
  662.   for (i=0; i<channelnum; i++)
  663.   {
  664.     guschan &c=channels[i];
  665.     if (c.inited&&(c.chstatus||(c.nextpos!=-1)))
  666.     {
  667.       selvoc(2*i);
  668.       setmode(c.mode|3);
  669.       fadevoldown();
  670.       selvoc(2*i+1);
  671.       setmode(c.mode|3);
  672.       fadevoldown();
  673.     }
  674.  
  675.     c.chstatus=0;
  676.   }
  677.  
  678.   for (i=0; i<channelnum; i++)
  679.   {
  680.     selvoc(2*i);
  681.     while (!(getvmode()&1));
  682.     selvoc(2*i+1);
  683.     while (!(getvmode()&1));
  684.   }
  685.  
  686.   for (i=0; i<channelnum; i++)
  687.   {
  688.     guschan &c=channels[i];
  689.     if (c.inited)
  690.     {
  691.       if (c.nextsample!=-1)
  692.       {
  693.         gussample &s=samples[c.nextsample];
  694.         unsigned char bit16=!!(s.type&mcpSamp16Bit);
  695.         c.startpos=s.pos;
  696.         if (bit16)
  697.           c.startpos=(c.startpos&0xC0000)|((c.startpos>>1)&0x1FFFF)|0x20000;
  698.         c.endpos=c.startpos+s.length;
  699.         c.loopstart=c.startpos+s.loopstart;
  700.         c.loopend=c.startpos+s.loopend;
  701.         c.samprate=s.samprate;
  702.         c.redlev=s.redlev;
  703.         c.smpptr=s.ptr;
  704.         c.mode=0;
  705.         if (bit16)
  706.           c.mode|=0x04;
  707.         c.cursamp=c.nextsample;
  708.         c.orgloop=0;
  709.         if (s.type&mcpSampLoop)
  710.         {
  711.           c.orgloop=1;
  712.           c.mode|=0x08;
  713.           if (s.type&mcpSampBiDi)
  714.             c.mode|=0x10;
  715.           selvoc(2*i);
  716.           setpoint8(c.loopstart, 1);
  717.           setpoint8(c.loopend, 2);
  718.           selvoc(2*i+1);
  719.           setpoint8(c.loopstart, 1);
  720.           setpoint8(c.loopend, 2);
  721.         }
  722.         else
  723.         {
  724.           selvoc(2*i);
  725.           setpoint8(c.startpos, 1);
  726.           setpoint8(c.endpos, 2);
  727.           selvoc(2*i+1);
  728.           setpoint8(c.startpos, 1);
  729.           setpoint8(c.endpos, 2);
  730.         }
  731.       }
  732.       if (c.nextpos!=-1)
  733.       {
  734.         unsigned long pos=c.startpos+(c.nextpos>>c.redlev);
  735.         if (c.mode&0x08)
  736.         {
  737.           if (pos>=c.loopend)
  738.             pos=c.loopstart+(pos-c.loopstart)%(c.loopend-c.loopstart);
  739.         }
  740.         else
  741.           if (pos>=c.endpos)
  742.             pos=c.endpos;
  743.         selvoc(2*i);
  744.         setpoint8(pos, 0);
  745.         selvoc(2*i+1);
  746.         setpoint8(pos, 0);
  747.         selvoc(2*i);
  748.         setmode(c.mode|(getmode()&0x40));
  749.         selvoc(2*i+1);
  750.         setmode(c.mode|(getmode()&0x40));
  751.       }
  752.       if (c.loopchange!=-1)
  753.       {
  754.         if (c.loopchange&&c.orgloop)
  755.           c.mode|=0x08;
  756.         else
  757.           c.mode&=~0x08;
  758.         selvoc(2*i);
  759.         setmode(c.mode|(getmode()&0x40));
  760.         if (c.mode&0x08)
  761.         {
  762.           setpoint8(c.loopstart, 1);
  763.           setpoint8(c.loopend, 2);
  764.         }
  765.         else
  766.         {
  767.           setpoint8(c.startpos, 1);
  768.           setpoint8(c.endpos, 2);
  769.         }
  770.         selvoc(2*i+1);
  771.         setmode(c.mode|(getmode()&0x40));
  772.         if (c.mode&0x08)
  773.         {
  774.           setpoint8(c.loopstart, 1);
  775.           setpoint8(c.loopend, 2);
  776.         }
  777.         else
  778.         {
  779.           setpoint8(c.startpos, 1);
  780.           setpoint8(c.endpos, 2);
  781.         }
  782.       }
  783.       selvoc(2*i);
  784.       if (!(getmode()&1))
  785.       {
  786.         unsigned long frq=muldiv64(muldiv64(c.orgfreq, c.samprate*masterfreq, c.orgdiv), activevoices, 154350);
  787.         selvoc(2*i);
  788.         setfreq(frq);
  789.         fadevol(c.pause?0:linvol[c.voll]);
  790.         selvoc(2*i+1);
  791.         setfreq(frq);
  792.         fadevol(c.pause?0:linvol[c.volr]);
  793.       }
  794.       else
  795.       {
  796.         selvoc(2*i);
  797.         fadevoldown();
  798.         selvoc(2*i+1);
  799.         fadevoldown();
  800.       }
  801.     }
  802.     else
  803.     {
  804.       selvoc(2*i);
  805.       fadevoldown();
  806.       selvoc(2*i+1);
  807.       fadevoldown();
  808.     }
  809.  
  810.     c.nextsample=-1;
  811.     c.nextpos=-1;
  812.     c.loopchange=-1;
  813.   }
  814.  
  815.   playerproc();
  816.  
  817.   stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
  818.   gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
  819. }
  820.  
  821. unsigned long doupload8(const void *buf, unsigned long guspos, unsigned long maxlen, unsigned short port);
  822. #pragma aux doupload8 parm [esi] [ebx] [ecx] [edx] modify [eax] value [ebx] = \
  823.   "pushf" \
  824.   "cli" \
  825.   "add dx,103h" \
  826.   "mov al,44h" \
  827.   "out dx,al" \
  828.   "add dx,2" \
  829.   "mov eax,ebx" \
  830.   "shr eax,16" \
  831.   "out dx,al" \
  832.   "sub dx,2" \
  833.   "mov al,43h" \
  834.   "out dx,al" \
  835.   "inc dx" \
  836. "lp:" \
  837.     "mov ax,bx" \
  838.     "out dx,ax" \
  839.     "mov al,[esi]" \
  840.     "add dx,3" \
  841.     "out dx,al" \
  842.     "sub dx,3" \
  843.     "inc ebx" \
  844.     "inc esi" \
  845.   "test bl,bl" \
  846.   "loopnz lp" \
  847.   "popf"
  848.  
  849. unsigned long doupload16(const void *buf, unsigned long guspos, unsigned long maxlen, unsigned short port);
  850. #pragma aux doupload16 parm [esi] [ebx] [ecx] [edx] modify [eax] value [ebx] = \
  851.   "pushf" \
  852.   "cli" \
  853.   "add dx,103h" \
  854.   "mov al,44h" \
  855.   "out dx,al" \
  856.   "add dx,2" \
  857.   "mov eax,ebx" \
  858.   "shr eax,16" \
  859.   "out dx,al" \
  860.   "sub dx,2" \
  861.   "mov al,43h" \
  862.   "out dx,al" \
  863.   "inc dx" \
  864.   "shr ecx,1" \
  865. "lp:" \
  866.     "mov ax,bx" \
  867.     "out dx,ax" \
  868.     "mov al,[esi]" \
  869.     "add dx,3" \
  870.     "out dx,al" \
  871.     "sub dx,3" \
  872.     "inc ebx" \
  873.     "mov ax,bx" \
  874.     "out dx,ax" \
  875.     "mov al,[esi+1]" \
  876.     "add dx,3" \
  877.     "out dx,al" \
  878.     "sub dx,3" \
  879.     "inc ebx" \
  880.     "add esi,2" \
  881.   "test bl,bl" \
  882.   "loopnz lp" \
  883.   "popf"
  884.  
  885. static void dmaupload()
  886. {
  887.   int upbytes;
  888.   if (dmapos&31)
  889.   {
  890.     upbytes=(-dmapos)&31;
  891.     if (upbytes>dmaleft)
  892.       upbytes=dmaleft;
  893.     if (!dma16bit)
  894.       doupload8(dmaxfer, dmapos, upbytes, gusPort);
  895.     else
  896.       doupload16(dmaxfer, dmapos, upbytes, gusPort);
  897.     dmaxfer=((char*)dmaxfer)+upbytes;
  898.     dmaleft-=upbytes;
  899.     dmapos+=upbytes;
  900.   }
  901.   if (!dmaleft)
  902.   {
  903.     dmaactive=0;
  904.     return;
  905.   }
  906.   upbytes=dmaleft;
  907.   if (upbytes>dmalen)
  908.     upbytes=dmalen;
  909.   if (((dmapos+upbytes)&0xC0000)>(dmapos&0xC0000))
  910.     upbytes=0x40000-(dmapos&0x3FFFF);
  911.  
  912.   dmaactive=1;
  913.   unsigned short adr=dmapos>>4;
  914.   if (gusDMA&4)
  915.     adr=(adr&0xC000)|((adr&0x3FFF)>>1);
  916.   outGUS(0x41, 0);
  917.   memcpy(dmabuf, dmaxfer, upbytes);
  918.   dmaStart(gusDMA, dmabuf, upbytes, 0x08);
  919.   dmaxfer=((char*)dmaxfer)+upbytes;
  920.   dmaleft-=upbytes;
  921.   dmapos+=upbytes;
  922.   outwGUS(0x42, adr);
  923.   outGUS(0x41, (gusDMA&4)|0x21|(dma16bit?0x40:0x00));
  924. }
  925.  
  926. static void slowupload()
  927. {
  928.   unsigned long endpos=dmapos+dmaleft;
  929.   unsigned long stpos=dmapos;
  930.   if (!dma16bit)
  931.     while (dmapos<endpos)
  932.       dmapos=doupload8((char*)dmaxfer+dmapos-stpos, dmapos, endpos-dmapos, gusPort);
  933.   else
  934.     while (dmapos<endpos)
  935.       dmapos=doupload16((char*)dmaxfer+dmapos-stpos, dmapos, endpos-dmapos, gusPort);
  936. }
  937.  
  938. static void handle_voice()
  939. {
  940. /*
  941.   unsigned long wave_ignore=0;
  942.   unsigned long volume_ignore=0;
  943.  
  944.   while (1)
  945.   {
  946.     unsigned char irq_source=inGUS(0x8F);
  947.  
  948.     unsigned char voice=irq_source&0x1F;
  949.  
  950.     if ((irq_source&0xC0)==0xC0)
  951.       break;
  952.  
  953.     unsigned long voice_bit=1<<voice;
  954.  
  955.     if (!(irq_source&0x80))
  956.       if (!(wave_ignore&voice_bit))
  957.       {
  958.         selvoc(voice);
  959.     if (!((inGUS(0x80)&0x08)||(inGUS(0x8D)&0x04)))
  960.       wave_ignore|=voice_bit;
  961.       }
  962.     if (!(irq_source&0x40))
  963.       if (!(volume_ignore&voice_bit))
  964.       {
  965.         selvoc(voice);
  966.     if (!(inGUS(0x8D)&0x08))
  967.           volume_ignore|=voice_bit;
  968.       }
  969.   }
  970. */
  971. }
  972.  
  973. static void irqrout()
  974. {
  975.   while (1)
  976.   {
  977.     unsigned char source=inpGUS(0x6);
  978.     if (!source)
  979.       break;
  980.     if (source&0x03)
  981.       inpGUS(0x100);
  982.     if (source&0x80)
  983.       if (inGUS(0x41)&0x40)
  984.         dmaupload();
  985.     if (source&0x04)
  986.     {
  987.       if (!usesystimer&&!paused)
  988.       {
  989.         if (gtimerpos<=256)
  990.           gtimerpos=gtimerlen;
  991.         else
  992.           gtimerpos-=256;
  993.         settimer(0x00);
  994.         settimerlen((gtimerpos<=256)?(256-gtimerpos):0);
  995.         settimer(0x04);
  996.         if (gtimerpos==gtimerlen)
  997.           if (doublechan)
  998.             processtickdc();
  999.           else
  1000.             processtick();
  1001.       }
  1002.       else
  1003.       {
  1004.         settimer(0x00);
  1005.         settimer(0x04);
  1006.       }
  1007.     }
  1008.     if (source&0x08)
  1009.     {
  1010.       settimer(0x00);
  1011.       settimer(0x04);
  1012.     }
  1013.     if (source&0x60)
  1014.       handle_voice();
  1015.   }
  1016. }
  1017.  
  1018. static void timerrout()
  1019. {
  1020.   if (paused)
  1021.     return;
  1022.   if (stimerpos<=65536)
  1023.     stimerpos=stimerlen;
  1024.   else
  1025.     stimerpos-=65536;
  1026.   tmSetNewRate((stimerpos<=65536)?stimerpos:65536);
  1027.   if (stimerpos==stimerlen)
  1028.     if (doublechan)
  1029.       processtickdc();
  1030.     else
  1031.       processtick();
  1032. }
  1033.  
  1034. void stackcall(void *);
  1035.  #pragma aux stackcall parm [eax] = \
  1036.   "mov word ptr oldssesp+4,ss" \
  1037.   "mov dword ptr oldssesp+0,esp" \
  1038.   "lss esp,stack" \
  1039.   "sti" \
  1040.   "call eax" \
  1041.   "cli" \
  1042.   "lss esp,oldssesp"
  1043.  
  1044. static void stackirq()
  1045. {
  1046.   if (stackused)
  1047.     return;
  1048.   stackused++;
  1049.   stackcall(irqrout);
  1050.   stackused--;
  1051. }
  1052.  
  1053. static void stacktimer()
  1054. {
  1055.   if (stackused)
  1056.     return;
  1057.   stackused++;
  1058.   stackcall(timerrout);
  1059.   stackused--;
  1060. }
  1061.  
  1062. static void voidtimer()
  1063. {
  1064. }
  1065.  
  1066. static void calcvols(guschan &c)
  1067. {
  1068.   short vl=(c.orgvol*mastervol/16)*amplify/65536;
  1069.   if (vl>=0x200)
  1070.     vl=0x1FF;
  1071.   short vr=(vl*((c.orgpan*masterpan/64)+0x80))>>8;
  1072.   vl-=vr;
  1073.  
  1074.   if (masterbal)
  1075.     if (masterbal<0)
  1076.       vr=(vr*(64+masterbal))>>6;
  1077.     else
  1078.       vl=(vl*(64-masterbal))>>6;
  1079.   c.voll=vl;
  1080.   c.volr=vr;
  1081. }
  1082.  
  1083. static int LoadSamples(sampleinfo *sil, int n)
  1084. {
  1085.   if (n>MAXSAMPLES)
  1086.     return 0;
  1087.  
  1088.   if (!mcpReduceSamples(sil, n, gusMem, mcpRedGUS))
  1089.     return 0;
  1090.  
  1091.   if (!doslowupload)
  1092.     irqInit(gusIRQ, stackirq, 1);
  1093.  
  1094.   mempos=0;
  1095.   int i;
  1096.   for (i=0; i<(2*n); i++)
  1097.   {
  1098.     sampleinfo &si=sil[i%n];
  1099.     if ((!!(si.type&mcpSamp16Bit))^(i<n))
  1100.       continue;
  1101.     gussample &s=samples[i%n];
  1102.     s.length=si.length;
  1103.     s.loopstart=si.loopstart;
  1104.     s.loopend=si.loopend;
  1105.     s.samprate=si.samprate;
  1106.     s.type=si.type;
  1107.     int bit16=!!(si.type&mcpSamp16Bit);
  1108.     s.redlev=(si.type&mcpSampRedRate4)?2:(si.type&mcpSampRedRate2)?1:0;
  1109.     s.pos=mempos;
  1110.     mempos+=(s.length+2)<<bit16;
  1111.  
  1112.     if (s.loopstart==s.loopend)
  1113.       s.type&=~mcpSampLoop;
  1114.  
  1115.     dma16bit=bit16;
  1116.     dmaleft=(s.length+2)<<dma16bit;
  1117.     dmaxfer=si.ptr;
  1118.     dmapos=s.pos;
  1119.     if (doslowupload)
  1120.     {
  1121.       slowupload();
  1122.       continue;
  1123.     }
  1124.  
  1125.     dmaupload();
  1126.     unsigned long t0=clock();
  1127.     while ((t0+(int)CLK_TCK*2)>clock())
  1128.       if (!dmaactive)
  1129.         break;
  1130.     if (!dmaactive)
  1131.       continue;
  1132.  
  1133.     irqClose();
  1134.     doslowupload=1;
  1135.     dmaactive=0;
  1136.  
  1137.     dma16bit=bit16;
  1138.     dmaleft=(s.length+2)<<dma16bit;
  1139.     dmaxfer=si.ptr;
  1140.     dmapos=s.pos;
  1141.     slowupload();
  1142.   }
  1143.  
  1144.   if (!doslowupload)
  1145.     irqClose();
  1146.  
  1147.   samplenum=n;
  1148. //  smSamplesTo8(sil, n);
  1149.  
  1150.   for (i=0; i<n; i++)
  1151.     samples[i].ptr=sil[i].ptr;
  1152.  
  1153.   return 1;
  1154. }
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160. static int OpenPlayer(int chan, void (*proc)())
  1161. {
  1162.   if (chan>32)
  1163.     chan=32;
  1164.  
  1165.   mixSetChan(chan);
  1166.  
  1167.   orgspeed=50*256;
  1168.  
  1169.   memset(channels, 0, sizeof(guschan)*chan);
  1170.   playerproc=proc;
  1171.   doublechan=chan<8;
  1172.   int i;
  1173.   if (doublechan)
  1174.   {
  1175.     initgus(2*chan);
  1176.     for (i=0; i<chan; i++)
  1177.     {
  1178.       selvoc(2*i);
  1179.       setpan(0);
  1180.       selvoc(2*i+1);
  1181.       setpan(15);
  1182.     }
  1183.   }
  1184.   else
  1185.     initgus(chan);
  1186.   channelnum=chan;
  1187.  
  1188.   selvoc(0);
  1189.   delayGUS();
  1190.   outpGUS0(0x09);
  1191.   delayGUS();
  1192.  
  1193.  
  1194.   if (usesystimer)
  1195.   {
  1196.     stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
  1197.     stimerpos=stimerlen;
  1198.     tmInit(stacktimer, (stimerpos<=65536)?stimerpos:65536);
  1199.   }
  1200.   else
  1201.   {
  1202.     irqInit(gusIRQ, stackirq, 1);
  1203.     gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
  1204.     gtimerpos=gtimerlen;
  1205.     settimerlen((gtimerpos<=256)?(256-gtimerpos):0);
  1206.     settimer(0x04);
  1207.  
  1208.     tmInit(voidtimer, 65536);
  1209.   }
  1210.   outpGUS8(0x04);
  1211.   outpGUS9(0x01);
  1212.  
  1213.   mcpNChan=chan;
  1214.  
  1215.   return 1;
  1216. }
  1217.  
  1218. static void ClosePlayer()
  1219. {
  1220.   mcpNChan=0;
  1221.  
  1222.   tmClose();
  1223.   if (!usesystimer)
  1224.     irqClose();
  1225.  
  1226.   initgus(14);
  1227.   channelnum=0;
  1228. }
  1229.  
  1230. unsigned short _disableint();
  1231. void _restoreint(unsigned short);
  1232. #pragma aux _disableint value [ax] = "pushf" "pop ax" "cli"
  1233. #pragma aux _restoreint parm [ax] = "push ax" "popf"
  1234.  
  1235. static void SetSpeed(unsigned long s)
  1236. {
  1237.   orgspeed=s;
  1238. }
  1239.  
  1240. static void SetFilter(unsigned char f)
  1241. {
  1242.   filter=f%8;
  1243. }
  1244.  
  1245. static void SetMasterVol(unsigned char vol)
  1246. {
  1247.   mastervol=vol;
  1248.   int i;
  1249.   for (i=0; i<channelnum; i++)
  1250.     calcvols(channels[i]);
  1251. }
  1252.  
  1253. static void SetMasterPan(signed char pan)
  1254. {
  1255.   masterpan=pan;
  1256.   int i;
  1257.   for (i=0; i<channelnum; i++)
  1258.     calcvols(channels[i]);
  1259. }
  1260.  
  1261. static void SetMasterBal(signed char bal)
  1262. {
  1263.   masterbal=bal;
  1264.   int i;
  1265.   for (i=0; i<channelnum; i++)
  1266.     calcvols(channels[i]);
  1267. }
  1268.  
  1269. static void SetMasterSpeed(unsigned short sp)
  1270. {
  1271.   if (sp<16)
  1272.     sp=16;
  1273.   relspeed=sp;
  1274. }
  1275.  
  1276. static void SetMasterFreq(unsigned short p)
  1277. {
  1278.   masterfreq=p;
  1279. }
  1280.  
  1281. static void SetAmplify(unsigned long amp)
  1282. {
  1283.   amplify=amp;
  1284.   int i;
  1285.   for (i=0; i<channelnum; i++)
  1286.     calcvols(channels[i]);
  1287.   mixSetAmplify(amp);
  1288. }
  1289.  
  1290.  
  1291. static void SetInstr(unsigned char ch, unsigned short samp)
  1292. {
  1293.   channels[ch].chstatus=1;
  1294.   channels[ch].nextsample=samp;
  1295.   channels[ch].loopchange=1;
  1296.   channels[ch].inited=1;
  1297. }
  1298.  
  1299.  
  1300.  
  1301. static void GetMixChannel(int ch, mixchannel &chn, int rate)
  1302. {
  1303.   chn.status=0;
  1304.  
  1305.   unsigned short is=_disableint();
  1306.   selvoc(doublechan?2*ch:ch);
  1307.   unsigned long pos=getpoint8(0);
  1308.   unsigned char mode=getmode();
  1309.   _restoreint(is);
  1310.   guschan &c=channels[ch];
  1311.  
  1312.   if ((paused&&!c.wasplaying)||(!paused&&(mode&1))||!c.inited)
  1313.     return;
  1314.  
  1315.   if (c.pause)
  1316.     chn.status|=MIX_MUTE;
  1317.  
  1318.   unsigned short resvoll,resvolr;
  1319.   resvoll=c.voll;
  1320.   resvolr=c.volr;
  1321.  
  1322.   chn.vols[0]=resvoll*4096/amplify;
  1323.   chn.vols[1]=resvolr*4096/amplify;
  1324.   chn.status|=((mode&0x08)?MIX_LOOPED:0)|((mode&0x10)?MIX_PINGPONGLOOP:0)|((mode&0x04)?MIX_PLAY16BIT:0);
  1325.   chn.step=muldiv64(muldiv64(muldiv64(c.orgfreq, masterfreq, 256), c.samprate, c.orgdiv), 1<<16, rate);
  1326.   if (mode&0x40)
  1327.     chn.step=-chn.step;
  1328.   chn.samp=c.smpptr;
  1329.   chn.length=c.endpos-c.startpos;
  1330.   chn.loopstart=c.loopstart-c.startpos;
  1331.   chn.loopend=c.loopend-c.startpos;
  1332.   chn.fpos=pos<<7;
  1333.   chn.pos=((pos>>9)&0xFFFFF)-c.startpos;
  1334.   if (filter>=6)
  1335.     chn.status|=MIX_INTERPOLATE;
  1336.   chn.status|=MIX_PLAYING;
  1337. }
  1338.  
  1339.  
  1340.  
  1341. static void SetVolume(unsigned char ch, signed short v)
  1342. {
  1343.   if (v>=0x100)
  1344.     v=0x100;
  1345.   if (v<0)
  1346.     v=0;
  1347.   channels[ch].orgvol=v;
  1348.   calcvols(channels[ch]);
  1349. }
  1350.  
  1351. static void SetPan(unsigned char ch, signed short p)
  1352. {
  1353.   if (p>=0x80)
  1354.     p=0x80;
  1355.   if (p<=-0x80)
  1356.     p=-0x80;
  1357.   channels[ch].orgpan=p;
  1358.   calcvols(channels[ch]);
  1359. }
  1360.  
  1361. static void SetReverbChorus(unsigned char ch, unsigned char reverb, unsigned char chorus)
  1362. {
  1363. }
  1364.  
  1365. static void SetPos(unsigned char ch, unsigned long pos)
  1366. {
  1367.   channels[ch].nextpos=pos;
  1368. }
  1369.  
  1370. static void SetFreq(unsigned char ch, unsigned long frq, unsigned long div)
  1371. {
  1372.   channels[ch].orgfreq=frq;
  1373.   channels[ch].orgdiv=div;
  1374. }
  1375.  
  1376. static void SetFreqLog(unsigned char ch, signed short note)
  1377. {
  1378.   channels[ch].orgfreq=8363;
  1379.   channels[ch].orgdiv=mcpGetFreq8363(-note);
  1380. }
  1381.  
  1382. static void Play(unsigned char ch, unsigned long frq, unsigned long div)
  1383. {
  1384.   channels[ch].orgfreq=frq;
  1385.   channels[ch].orgdiv=div;
  1386.   channels[ch].nextpos=0;
  1387.   channels[ch].loopchange=1;
  1388. }
  1389.  
  1390. static void PlayLog(unsigned char ch, signed short note)
  1391. {
  1392.   Play(ch, 8363, mcpGetFreq8363(-note));
  1393. }
  1394.  
  1395. static void Stop(unsigned char ch)
  1396. {
  1397.   channels[ch].nextpos=-1;
  1398.   channels[ch].chstatus=1;
  1399. }
  1400.  
  1401. static void LeaveLoop(unsigned char ch)
  1402. {
  1403.   channels[ch].loopchange=0;
  1404. }
  1405.  
  1406. static void Reset(unsigned char ch)
  1407. {
  1408.   unsigned char p=channels[ch].pause;
  1409.   memset(channels+ch, 0, sizeof(guschan));
  1410.   channels[ch].pause=p;
  1411. }
  1412.  
  1413. static void Pause(unsigned char p)
  1414. {
  1415.   if (p==paused)
  1416.     return;
  1417.   int i;
  1418.   if (paused)
  1419.   {
  1420.     for (i=0; i<channelnum; i++)
  1421.       if (doublechan)
  1422.       {
  1423.         if (channels[i].wasplaying)
  1424.         {
  1425.           selvoc(2*i);
  1426.           setmode(channels[i].mode|(getmode()&0x40));
  1427.           selvoc(2*i+1);
  1428.           setmode(channels[i].mode|(getmode()&0x40));
  1429.         }
  1430.       }
  1431.       else
  1432.         if (channels[i].wasplaying)
  1433.         {
  1434.           selvoc(i);
  1435.           setmode(channels[i].mode|(getmode()&0x40));
  1436.         }
  1437.     gtimerpos=0;
  1438.     stimerpos=0;
  1439.     paused=0;
  1440.     if (!usesystimer)
  1441.       settimer(0x04);
  1442.   }
  1443.   else
  1444.   {
  1445.     paused=1;
  1446.     if (!usesystimer)
  1447.       settimer(0x00);
  1448.     for (i=0; i<channelnum; i++)
  1449.       if (doublechan)
  1450.       {
  1451.         selvoc(2*i);
  1452.         channels[i].wasplaying=!(getmode()&1);
  1453.         setmode(3|(getmode()&0x40));
  1454.         selvoc(2*i+1);
  1455.         setmode(3|(getmode()&0x40));
  1456.       }
  1457.       else
  1458.       {
  1459.         selvoc(i);
  1460.         channels[i].wasplaying=!(getmode()&1);
  1461.         setmode(3|(getmode()&0x40));
  1462.       }
  1463.   }
  1464. }
  1465.  
  1466. static int GetStatus(int ch)
  1467. {
  1468.   unsigned is=_disableint();
  1469.   selvoc(doublechan?2*ch:ch);
  1470.   int rv=!(getmode()&1);
  1471.   if (paused&&channels[ch].wasplaying)
  1472.     rv=1;
  1473.   _restoreint(is);
  1474.   return rv;
  1475. }
  1476.  
  1477. static void SET(int ch, int opt, int val)
  1478. {
  1479.   switch (opt)
  1480.   {
  1481.   case mcpGSpeed:
  1482.     SetSpeed(val);
  1483.     break;
  1484.   case mcpCInstrument:
  1485.     SetInstr(ch, val);
  1486.     break;
  1487.   case mcpCMute:
  1488.     channels[ch].pause=val;
  1489.     break;
  1490.   case mcpCStatus:
  1491.     if (!val)
  1492.       Stop(ch);
  1493.     break;
  1494.   case mcpCReset:
  1495.     Reset(ch);
  1496.     break;
  1497.   case mcpCVolume:
  1498.     SetVolume(ch, val);
  1499.     break;
  1500.   case mcpCPanning:
  1501.     SetPan(ch, val);
  1502.     break;
  1503.   case mcpMasterAmplify:
  1504.     SetAmplify(val);
  1505.     break;
  1506.   case mcpMasterPause:
  1507.     Pause(val);
  1508.     break;
  1509.   case mcpCPosition:
  1510.     SetPos(ch, val);
  1511.     break;
  1512.   case mcpCPitch:
  1513.     SetFreqLog(ch, val);
  1514.     break;
  1515.   case mcpCPitchFix:
  1516.     SetFreq(ch, val, 0x10000);
  1517.     break;
  1518.   case mcpCPitch6848:
  1519.     SetFreq(ch, 6848, val);
  1520.     break;
  1521.   case mcpMasterVolume:
  1522.     SetMasterVol(val);
  1523.     break;
  1524.   case mcpMasterPanning:
  1525.     SetMasterPan(val);
  1526.     break;
  1527.   case mcpMasterBalance:
  1528.     SetMasterBal(val);
  1529.     break;
  1530.   case mcpMasterSpeed:
  1531.     SetMasterSpeed(val);
  1532.     break;
  1533.   case mcpMasterPitch:
  1534.     SetMasterFreq(val);
  1535.     break;
  1536.   case mcpMasterFilter:
  1537.     SetFilter(val);
  1538.     break;
  1539.   }
  1540. }
  1541.  
  1542. static int GET(int ch, int opt)
  1543. {
  1544.   switch (opt)
  1545.   {
  1546.   case mcpCStatus:
  1547.     return !!GetStatus(ch);
  1548.   case mcpCMute:
  1549.     return !!channels[ch].pause;
  1550.   case mcpGTimer:
  1551.     return tmGetTimer();
  1552.   }
  1553.   return 0;
  1554. }
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563. static int initu(const deviceinfo &c)
  1564. {
  1565.   doslowupload=(c.opt&SS_GUS_SLOWUPLOAD)||(c.dma==-1)||(c.irq==-1);
  1566.   usesystimer=(c.opt&SS_GUS_SYSTIMER)||(c.irq==-1);
  1567.  
  1568.   dmaactive=0;
  1569.   dmalen=32768;
  1570.   dmabuf=dmaAlloc(dmalen, dmasel);
  1571.   dmalen&=~31;
  1572.   stack=new char [stacksize];
  1573.   if (!stack||!dmabuf)
  1574.     return 0;
  1575.   stack+=stacksize;
  1576.   stackused=0;
  1577.  
  1578.   if (!mixInit(GetMixChannel, 1))
  1579.     return 0;
  1580.  
  1581.   int i;
  1582.  
  1583.   if (!testPort(c.port))
  1584.     return 0;
  1585.  
  1586.   gusPort=c.port;
  1587.   gusIRQ=c.irq;
  1588.   gusDMA=c.dma;
  1589. //  gusIRQ2=c.irq2;
  1590.   gusDMA2=c.dma2;
  1591.  
  1592.   channelnum=0;
  1593.   filter=0;
  1594.  
  1595.   initgus(14);
  1596.  
  1597.   relspeed=256;
  1598.   paused=0;
  1599.  
  1600.   mastervol=64;
  1601.   masterpan=64;
  1602.   masterbal=0;
  1603.   masterfreq=256;
  1604.   amplify=65536;
  1605.  
  1606.   linvol[0]=0;
  1607.   linvol[512]=0x0FFF;
  1608.   for (i=1; i<512; i++)
  1609.   {
  1610.     int j,k;
  1611.     k=i;
  1612.     for (j=0x0600; k; j+=0x0100)
  1613.       k>>=1;
  1614.     linvol[i]=j|((i<<(8-((j-0x700)>>8)))&0xFF);
  1615.   }
  1616.  
  1617.   mcpLoadSamples=LoadSamples;
  1618.   mcpOpenPlayer=OpenPlayer;
  1619.   mcpClosePlayer=ClosePlayer;
  1620.   mcpSet=SET;
  1621.   mcpGet=GET;
  1622.  
  1623.   return 1;
  1624. }
  1625.  
  1626.  
  1627. static void closeu()
  1628. {
  1629.   mcpOpenPlayer=0;
  1630.   mixClose();
  1631.   dmaFree(dmasel);
  1632.   delete (char near *)(stack-stacksize);
  1633. }
  1634.  
  1635. static int detectu(deviceinfo &c)
  1636. {
  1637.   if (!getcfg())
  1638.   {
  1639.     if (c.port==-1)
  1640.       return 0;
  1641.     gusPort=c.port;
  1642.     gusIRQ=c.irq;
  1643. //    gusIRQ2=(c.irq2==-1)?c.irq:c.irq2;
  1644.     gusDMA=c.dma;
  1645.     gusDMA2=(c.dma2==-1)?c.dma:c.dma2;
  1646.   }
  1647.   else
  1648.   {
  1649.     if (c.port!=-1)
  1650.       gusPort=c.port;
  1651.     if (c.irq!=-1)
  1652.       gusIRQ=c.irq;
  1653. //    if (c.irq2!=-1)
  1654. //      gusIRQ2=c.irq2;
  1655.     if (c.dma!=-1)
  1656.       gusDMA=c.dma;
  1657.     if (c.dma2!=-1)
  1658.       gusDMA2=c.dma2;
  1659.   }
  1660.  
  1661.   if (!testPort(gusPort))
  1662.     return 0;
  1663.   c.subtype=-1;
  1664.   c.dev=&mcpUltraSound;
  1665.   c.port=gusPort;
  1666.   c.port2=-1;
  1667. //  c.irq=(gusIRQ<gusIRQ2)?gusIRQ:gusIRQ2;
  1668. //  c.irq2=(gusIRQ<gusIRQ2)?gusIRQ2:gusIRQ;
  1669.   c.irq=gusIRQ;
  1670. //    c.irq2=gusIRQ2;
  1671.   c.irq2=-1;
  1672.   c.dma=gusDMA;
  1673.   c.dma2=gusDMA2;
  1674.   if ((c.opt&SS_GUS_SLOWUPLOAD)&&(c.opt&SS_GUS_SYSTIMER))
  1675.     c.irq=-1;
  1676.   if ((c.opt&SS_GUS_SLOWUPLOAD)||(c.irq==-1))
  1677.   {
  1678.     c.dma=-1;
  1679.     c.dma2=-1;
  1680.   }
  1681.   c.mem=gusMem;
  1682.   c.chan=32;
  1683.   return 1;
  1684. }
  1685.  
  1686. extern "C" sounddevice mcpUltraSound={SS_WAVETABLE, "Gravis UltraSound", detectu, initu, closeu};
  1687.  
  1688. #include "devigen.h"
  1689. #include "psetting.h"
  1690.  
  1691. static unsigned long gusGetOpt(const char *sec)
  1692. {
  1693.   unsigned long opt=0;
  1694.   if (cfGetProfileBool(sec, "gusslowupload", 1, 1))
  1695.     opt|=SS_GUS_SLOWUPLOAD;
  1696.   if (cfGetProfileBool(sec, "gussystemtimer", 1, 1))
  1697.     opt|=SS_GUS_SYSTIMER;
  1698.   return opt;
  1699. }
  1700.  
  1701. extern "C" devaddstruct mcpGUSAdd = {gusGetOpt, 0, 0, 0};
  1702.